﻿namespace EyeOpen.Crypt.ViewModel.Silverlight
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using EyeOpen.Crypt.Client.BootStrapper;
    using EyeOpen.Crypt.Client.Service;
    using EyeOpen.IO;
    using EyeOpen.ViewModel.Silverlight;

    public partial class CryptViewModel
    {
        private readonly Dictionary<string, List<string>> errors;
        private readonly EncryptServiceAsynchronousFactory factory;
        private readonly IEncryptionServiceAsynchronous proxy;
        private string cryptText;
        private string password;
        private string retypedpassword;
        private string errorMessage;
        private bool isBusy;
        private bool encryptInfoIsAvailable;
        private EncryptionType encryptionType = EncryptionType.NotDefined;
        private bool passwordHasErrors = true;
        private bool retypedpasswordHasErrors = true;
        private bool cryptTextHasErrors = true;
        private int clearTextLenght;
        private int encryptedTextLenght;
        private int compressedTextLenght;

        public CryptViewModel()
        {
            factory = new EncryptServiceAsynchronousFactory();
            proxy = factory.CreateServiceContext();
            proxy.CryptDecryptLoaded += CryptDecryptLoaded;
            errors = new Dictionary<string, List<string>>();
            EncryptDecryptCommand = new CommandStatus(this, ExecuteCryptDecrypt, CanExecuteCryptDecrypt);
            CopyToClipboadCommand = new CommandStatus(this, ExecuteCopyToClipboard, CanExecuteCopyToClipboard);
        }


        public string Password
        {
            get
            {
                return password;
            }

            set
            {
                if (string.IsNullOrWhiteSpace(value) || (value.Length < 8 || value.Length > 24))
                {
                    PasswordHasErrors = true;
                    throw new ArgumentException("Password can't be null or empty and must have at least 8 characters.");
                }

                password = value;
                PasswordHasErrors = false;
                NotifyErrorsChanged("Password");
                OnPropertyChanged("Password");
            }
        }

        public string RetypedPassword
        {
            get
            {
                return retypedpassword;
            }

            set
            {
                if (string.IsNullOrWhiteSpace(value) || (string.IsNullOrWhiteSpace(Password) || !Password.Equals(value)) || PasswordHasErrors)
                {
                    RetypedPasswordHasErrors = true;
                    throw new ArgumentException("Password doesn't match.");
                }

                retypedpassword = value;
                RetypedPasswordHasErrors = false;
                NotifyErrorsChanged("RetypedPassword");
                OnPropertyChanged("RetypedPassword");
            }
        }

        public string CryptText
        {
            get
            {
                return cryptText;
            }

            set
            {
                if (string.IsNullOrWhiteSpace(value) && (value.Length < 3))
                {
                    CryptTextHasErrors = true;
                    throw new ArgumentException("CryptText can't be null or empty and must have at least 3 characters.");
                }

                cryptText = value;
                CryptTextHasErrors = false;
                NotifyErrorsChanged("CryptText");
                OnPropertyChanged("CryptText");
            }
        }

        public bool EncryptInfoIsAvailable
        {
            get
            {
                return encryptInfoIsAvailable;
            }

            set
            {
                encryptInfoIsAvailable = value;
                OnPropertyChanged("EncryptInfoIsAvailable");
            }
        }

        /// <summary>
        /// Returns true if the application is busy with encryption/decryption.
        /// </summary>
        public bool IsBusy
        {
            get
            {
                return isBusy;
            }

            set
            {
                isBusy = value;
                OnPropertyChanged("IsBusy");
            }
        }

        /// <summary>
        /// Returns true if the crypt/decrypt button can be enabled.
        /// </summary>
        public bool IsEnabled
        {
            get
            {
                return !CryptTextHasErrors && !PasswordHasErrors && !RetypedPasswordHasErrors;
            }
        }

        /// <summary>
        /// Returns true if the copy to clipboad button can be enabled.
        /// </summary>
        public bool IsClipboardEnabled
        {
            get
            {
                return !CryptTextHasErrors;
            }
        }

        public override bool HasErrors
        {
            get
            {
                return errors.Count > 0;
            }
        }

        public string ErrorMessage
        {
            get
            {
                return errorMessage;
            }

            set
            {
                errorMessage = value;
                OnPropertyChanged("ErrorMessage");
            }
        }

        public EncryptionType EncryptionType
        {
            get
            {
                return encryptionType;
            }

            set
            {
                encryptionType = value;
                OnPropertyChanged("EncryptionType");
            }
        }

        public int ClearTextLenght
        {
            get
            {
                return clearTextLenght;
            }

            set
            {
                clearTextLenght = value;
                OnPropertyChanged("ClearTextLenght");
            }
        }

        public int EncryptedTextLenght
        {
            get
            {
                return encryptedTextLenght;
            }

            set
            {
                encryptedTextLenght = value;
                OnPropertyChanged("EncryptedTextLenght");
            }
        }

        public int CompressedTextLenght
        {
            get
            {
                return compressedTextLenght;
            }

            set
            {
                compressedTextLenght = value;
                OnPropertyChanged("CompressedTextLenght");
            }
        }

        public IErrorShower ErrorShower
        {
            get;
            set;
        }


        private bool PasswordHasErrors
        {
            get
            {
                return passwordHasErrors;
            }

            set
            {
                passwordHasErrors = value;
                OnPropertyChanged("PasswordHasErrors");
                OnPropertyChanged("IsEnabled");
            }
        }

        private bool RetypedPasswordHasErrors
        {
            get
            {
                return retypedpasswordHasErrors;
            }

            set
            {
                retypedpasswordHasErrors = value;
                OnPropertyChanged("RetypedPasswordHasErrors");
                OnPropertyChanged("IsEnabled");
            }
        }

        private bool CryptTextHasErrors
        {
            get
            {
                return cryptTextHasErrors;
            }

            set
            {
                cryptTextHasErrors = value;
                OnPropertyChanged("CryptTextHasErrors");
                OnPropertyChanged("IsEnabled");
                OnPropertyChanged("IsClipboardEnabled");
            }
        }

        public override IEnumerable GetErrors(string propertyName)
        {
            return errors.Values;
        }

        private bool CanExecuteCryptDecrypt()
        {
            return IsEnabled;
        }

        private bool CanExecuteCopyToClipboard()
        {
            return IsClipboardEnabled;
        }
    }
}